#include "myStdio.h"

FILE_ *fopen_(const char *path_name, const char *mode)
{
    int flags = 0;
    int defaultMode = 0666;
    //检查以那种方式打开文件
    if (strcmp(mode, "r") == 0)
    {
        flags |= O_RDONLY;
    }
    else if (strcmp(mode, "w") == 0)
    {
        flags |= (O_WRONLY | O_CREAT | O_TRUNC);
    }
    else if (strcmp(mode, "a") == 0)
    {
        flags |= (O_WRONLY | O_CREAT | O_APPEND);
    }
    else 
    {
        perror("fopen");
    }

    int fd = 0;

    //若是创建文件则加上默认的文件权限
    if (flags & O_RDONLY) fd = open(path_name, flags);
    else fd = open(path_name, flags, defaultMode);
    if (fd < 0)
    {
        const char *err = strerror(errno);
        write(2, err, strlen(err));//将错误信息输出到标准输出
        return NULL;
    }

    FILE_ *fp = (FILE_*)malloc(sizeof(FILE_));
    assert(fp);

    fp->flags = SYNC_LINE;
    fp->flieno = fd;
    fp->cap = SIZE;
    fp->size = 0;
    memset(fp->buffer, 0, SIZE);

    return fp;
}

void fwrite_(const void *ptr, int num, FILE_ *fp)
{
    memcpy(fp->buffer + fp->size, ptr, num);//不考虑缓冲区溢出
    fp->size += num;

    //判断是否刷新缓冲区
    if (fp->flags & SYNC_NOW)
    {
        write(fp->flieno, fp->buffer, fp->size);//将用户缓冲区的内容传到内核空间
        fp->size = 0;//清空缓冲区
    }
    else if (fp->flags & SYNC_LINE)
    {
        if (fp->buffer[fp->size - 1] == '\n') 
        {
            // 不考虑aaaa\nbbbb这种情况
            write(fp->flieno, fp->buffer, fp->size);
            fp->size = 0;
        }
    }
    else if (fp->flags & SYNC_FULL)
    {
        if (fp->size == fp->cap)
        {
            write(fp->flieno, fp->buffer, fp->size);
            fp->size = 0;
        }
    }
    else 
    {
        perror("fwrite_");
    }
}

void fflush_(FILE_ *fp)
{
    if (fp->size > 0) write(fp->flieno, fp->buffer, fp->size);
    fsync(fp->flieno);//强制将内核缓冲区的内容同步到磁盘
    fp->size = 0;
}

void fclose_(FILE_ *fp)
{
    fflush_(fp);
    close(fp->flieno);
}
